/**
 * 
 */
package com.ginger.security;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import com.ginger.model.User;
import com.ginger.service.AuthService;

/**
 * @Description: 安全校验流程
 * @author 姜锋
 * @date 2018年6月25日 上午10:20:25
 * @version V1.0
 */
public class CustomRealm extends AuthorizingRealm {
	@Autowired
	AuthService authService;

	// 认证
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		// 1 获得身份信息
		String principal = (String) token.getPrincipal();
		// 3 通过用户名查询验证
		User user = authService.findByUserCode(principal);
		// 3.1账号不存在
		if (null == user) {
			throw new UnknownAccountException();
		}
		// 3.2账号锁定
		if (user.getLocked()) {
			throw new LockedAccountException();
		}
		// 3.3帐号已删除
		if (user.getDisabled()) {
			throw new DisabledAccountException();
		}
		Sha256Hash sha256Hash = new Sha256Hash(token.getCredentials());
		String encryptedPassword = sha256Hash.toString();
		// 3.4密码错误
		if (!encryptedPassword.equals(user.getPassword())) {
			throw new IncorrectCredentialsException();
		}
		// 4 将密码信息交予shiro，自动进行校验
		return new SimpleAuthenticationInfo(user, encryptedPassword, getName());
	}
	// 授权
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		// 获取主体信息,认证时自定义传入user实例
		Object o = principals.getPrimaryPrincipal();
		User activeUser = (User) o;
		// 获取用户id
		Long userId = activeUser.getUserId();
		List<String> permsList;
		if (userId == 1) {
			permsList = authService.queryAdminPerms();
			// 获取该用户所有权限
		} else {
			permsList = authService.queryRolePermCodeByUser(activeUser.getUserId());
		}
		if (permsList == null) {
			permsList = new ArrayList<>();
		}
		// 为所有用户添加首页权限
		// TODO 可设置公共权限
		permsList.add("system:main");
		// 用户权限列表
		Set<String> permsSet = new HashSet<String>();
		String perms;
		for (int i = 0; i < permsList.size(); i++) {
			perms = permsList.get(i);
			if (StringUtils.isBlank(perms)) {
				continue;
			}
			// 拆分表内权限组合[user:query,perm:del]
			permsSet.addAll(Arrays.asList(perms.trim().split(",")));
		}
		List<String> roleList;
		if (userId == 1) {
			roleList = authService.checkAllRole();
			// 获取该用户所有权限
		} else {
			roleList = authService.checkRole(activeUser.getUserName());
		}
		if (roleList == null) {
			roleList = new ArrayList<>();
		}
		// 为所有用户添加首页权限
		// TODO 可设置公共角色
		permsList.add("commonUser");
		// 用户权限列表
		Set<String> rolosSet = new HashSet<String>();
		String roles;
		for (int i = 0; i < roleList.size(); i++) {
			roles = roleList.get(i);
			if (StringUtils.isBlank(roles)) {
				continue;
			}
			// 拆分表内权限组合[user:query,perm:del]
			rolosSet.addAll(Arrays.asList(roles.trim().split(",")));
		}
		// 返回认证信息 由shiro自动校验
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.setStringPermissions(permsSet);
		info.setRoles(rolosSet);
		return info;
	}
	/**
	 * 清空当前用户权限信息
	 */
	public void clearCachedAuthorizationInfo() {
		PrincipalCollection principalCollection = SecurityUtils.getSubject().getPrincipals();
		SimplePrincipalCollection principals = new SimplePrincipalCollection(principalCollection, getName());
		super.clearCachedAuthorizationInfo(principals);
	}
	/**
	 * 指定principalCollection 清除
	 */
	public void clearCachedAuthorizationInfo(PrincipalCollection principalCollection) {
		SimplePrincipalCollection principals = new SimplePrincipalCollection(principalCollection, getName());
		super.clearCachedAuthorizationInfo(principals);
	}
}
